// argsv/arg_iter.hh
// Written by, Sohail Qayum Malik[sqm@cyberian.pk]

#include <iostream>
#include <iterator>

//using namespace::std;

#ifndef		NON_CONST_ARGUMENT_ITERATOR_HH
#define		NON_CONST_ARGUMENT_ITERATOR_HH

template <class Tp, typename history>
class arg_iter : public std::iterator<std::random_access_iterator_tag, arg_iter<Tp, history> > {

	// Previously it was const, problems with the pre/postincrement made me 
	// make it non-const
 	Tp container;
  
	public:

	   typedef 	typename history::value_type	value_type;

	   value_type operator *(void) {

              return *container;		   
           }

	   value_type operator [](const int n) {

	      //cout<<"JKJKKJ"<<endl;		   

              return container[n];
           }
           
           bool operator()(const int n) {
           
/*                         
              bool ret = 0;
              value_type foo = container[n];
              
              if ( foo() ) {
              
                 ret = 1;
              }
*/
              
              return container[n]();
           }		   

           //Bidirectional Iterator
	   //Predecrement
	   arg_iter<Tp, value_type>& operator --(void) {

              return *this;		   
           }
	   //Postdecrement
	   arg_iter<Tp, value_type> operator --(int /* unused */) {

              arg_iter<Tp, value_type> tmp = *this;

	      --(*this);
	      
	      return tmp;
           }		   

	   //Input iterator is refinement of Trivial iterator
	   //Preincrement
	   arg_iter<Tp, value_type>& operator ++(void) {
		   
              ++container; 

	      return *this;
           }

           //Postincrement 
	   arg_iter<Tp, value_type> operator ++(int /* unused */) {

              arg_iter<Tp, value_type> tmp = *this;

	      ++(*this);

	      return tmp;
           }

	   arg_iter<Tp, history>(const arg_iter<Tp, value_type>& ref) : container(ref.container) {
           }		   

           //Trivial Iterator is refinement of Assignable type
	   arg_iter<Tp, history>(Tp container) : container(container) {		   
           }

           void swap(arg_iter<Tp, value_type>& x, arg_iter<Tp, value_type>& y) {
			
	      arg_iter<Tp, value_type> tmp = x;
              x = y;
	      y = tmp;
           }			 

	   arg_iter<Tp, value_type>& operator=(arg_iter<Tp, value_type>& ref) {

	      return ref; 		 
           }

           //Trivial Iterator is refinement of Equality comparable type
           /**
	    * iterA is const_iterator and iterB is iterator. When I do
	    * if (iterA == iterB); then I get the following error...
	    * error: passing 'const arg_iter<argument<arg_history> >' as 
	   'this' argument of 'bool arg_iter<_Tp>::operator==(arg_iter<_Tp>&) 
	   [with _Tp = argument<arg_history>]' discards qualifiers 
	    * Now I should do... if (iterB == iterA); **/
	   bool operator==(const arg_iter<Tp, value_type>& ref) {
 
              return (container == ref.container); 
	   }		 

           bool operator==(arg_iter<Tp, value_type>& ref) {

              return (container == ref.container);		   
           }	 

	   bool operator!=(const arg_iter<Tp, value_type>& ref) {

	      return (container != ref.container);  	   
           }

           bool operator!=(arg_iter<Tp, value_type>& ref) {

	      return (container != ref.container);
	   } 		 
	         	
           //Trivial Iterator is refinement of Default Constructible type
	   //A type that is Default Constructible is not necessarily
	   //assignable, that is, a statement like the following
           //X x = X();
           //may not be a valid statment.
	   //But here at the g++ it works.
	   arg_iter(void) {
	   }
};

#endif
